package org.linhadig.service;

import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import org.linhadig.service.domain.Data;
import org.linhadig.service.domain.LinhaDigitavel;
import org.linhadig.service.domain.Valor;

public class CalculadorDeLinhaDigitavel {
	
	private DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
	private Date dataBase = null;
	private final String DATA_BASE = "07/10/1997";
	
	
	public CalculadorDeLinhaDigitavel() {
		try {
			dataBase = df.parse(DATA_BASE);
		} catch(Exception e) { }
	}
	
	public LinhaDigitavel calcularNovaLinhaDigitavel(LinhaDigitavel oldL, Data data, Valor valor) {
		LinhaDigitavel newL = new LinhaDigitavel();
		
		newL.setCampo1( oldL.getCampo1() );
		newL.setCampo2( oldL.getCampo2() );
		newL.setCampo3( oldL.getCampo3() );
		newL.setCampo4( oldL.getCampo4() );
		newL.setCampo5( oldL.getCampo5() );
		newL.setCampo6( oldL.getCampo6() );
		
		String campo8 = obterFatorDeVencimento(data) + obterNovoValor(valor);
		newL.setCampo8( campo8 );
		
		newL.setCampo7( obterDVGeral(newL, data, valor) );
		return newL;
	}
	
	public String obterDVGeral(LinhaDigitavel ld, Data data, Valor valor) {
		String repNum = obterRepresentacaoNumerica(ld, data, valor);
		
		int somaGeral = 0;
		int vetor_tam = repNum.length();
		int contador = 0;
		for (int i = vetor_tam-1; i >= 0; i--) {
			int fator_mult = contador++ % 8 + 2;
			int num = new Integer(repNum.substring(i, i+1));
			somaGeral = somaGeral + num * fator_mult;
		}
		
		Integer dv = null;
		int restoGeral = 11 - somaGeral % 11;
		if (restoGeral == 0 || restoGeral == 10 || restoGeral == 11) {
			dv = 1;
		} else {
			dv = restoGeral;
		}
		return dv.toString();
	}
	
	public String obterRepresentacaoNumerica(LinhaDigitavel ld, Data data, Valor valor) {
		String repNum = ld.getCampo1() +  
					   ld.getCampo2().substring(0, ld.getCampo2().length() - 1) + 
					   ld.getCampo3() +
					   ld.getCampo4().substring(0, ld.getCampo4().length() - 1) +
					   ld.getCampo5() + 
					   ld.getCampo6().substring(0, ld.getCampo6().length() - 1) +
					   ld.getCampo8();
		
		StringBuffer sb = new StringBuffer();
		sb
			.append( obterBanco(repNum) )
			.append( obterMoeda(repNum) )
			.append( obterFatorDeVencimento(data) )
			.append( obterNovoValor(valor))
			.append( obterNossoNumero(repNum))
			.append( obterAgenciaCodCedente(repNum))
			;
		
		return sb.toString();
	}
	
	
	private String obterFatorDeVencimento(Data data) {
		long mili = data.getData().getTime() - dataBase.getTime();
		return new Long(TimeUnit.MILLISECONDS.toDays(mili)).toString();
	}
	
	private String obterNovoValor(Valor valor) {
		DecimalFormat df = new DecimalFormat("00000000.00");
		return df.format(valor.getValor() ).replace(".", "").replace(",", "");
	}
	
	public String obterBanco(String ld) {
		return ld.substring(0, 3);
	}
	
	public String obterMoeda(String ld) {
		return ld.substring(3,4);
	}
	
	public String obterNossoNumero(String ld) {
		return ld.substring(4, 16);
	}
	
	public String obterAgenciaCodCedente(String ld) {
		return ld.substring(16, 29);
	}

}